using Basis;
using DG.Tweening;
using System;
using System.Collections;
using UnityEngine;

namespace NL.Advanced
{
    public partial class CameraBase
    {
        public void LookAtNotFocus(Transform where)
        {
            _DoLookAt(where, 0f, Config.FocusSpeed, false, 0);

        }
        public void LookAt(Transform where, float camerahigh = 0, float speed = 0f, bool suitforbound = false)
        {
            _DoLookAt(where,
                camerahigh > 0 ? camerahigh : Config.HighDefault,
                speed > 0 ? speed : Config.FocusSpeed,
                suitforbound);
        }

        /// <summary>
        /// 聚焦到（观察）一个位置
        /// </summary>
        /// <param name="where">位置</param>
        /// <param name="camerahigh">摄像机高度（从多高的位置观测）</param>
        /// <param name="speed">相机移动速度</param>
        /// <param name="suitforbound">视场适应物体的bound（需观测物体有bound）</param>
        /// <param name="boundzoom">观测物体视场的缩放比例</param>
        /// <code>
        /// 视场：
        ///               bound
        ///                ↓
        ///       \       ____       /
        ///        \--a---|物|---a--/       boundzoom=2a/bound
        ///         \     ----     /
        ///          \            /
        ///           \          /
        ///            \________/
        /// </code>
        protected void _DoLookAt(Transform where, float camerahigh, float speed, bool suitforbound, float boundzoom = 0)
        {
            if (IsRouting) return;
            // transform.localRotation = Quaternion.identity;

            var pos = _GetLookAtPosition(where.position, camerahigh);

            //TODO 临时处理一下相机聚焦坐标（gaolei）
            //pos += new Vector3(10f, 10f, 10f);

            transform.DOKill();

            if (speed > 999999)
            {
                transform.position = pos;

                if (_OnLookAtEnd != null)
                {
                    _OnLookAtEnd.Invoke();
                }

                if (suitforbound)
                {
                    _SuitViewFor(where, boundzoom, Config.FocusDelay);
                }
            }
            else
            {
                transform.DOMove(pos, speed).SetSpeedBased().SetEase(Config.FocusEase)
                .onComplete = () =>
                {
                    if (_OnLookAtEnd != null)
                    {
                        _OnLookAtEnd.Invoke();
                    }

                    if (suitforbound)
                    {
                        _SuitViewFor(where, boundzoom, Config.FocusDelay);
                    }
                };
            }
        }

        Vector3 _SavedLookPoint;

        private Quaternion _SavedLookRot;
        //float _SavedLookPointY;
        public CameraBase SaveLookPoint()
        {
            _SavedLookPoint = transform.position;
            _SavedLookRot = Forward.rotation;

            return this;
        }

        public CameraBase ResumeLookPoint()
        {
            transform.position = _SavedLookPoint;
            Forward.rotation = _SavedLookRot;

            return this;
        }
        public void LookBack(Transform where)
        {
            if (IsRouting) return;

            if (_SavedLookPoint.y < 5) return;

            var pos = _GetLookAtPosition(where.position, _SavedLookPoint.y);

            transform.DOKill();
            transform.DOMove(pos, Config.FocusSpeed * 2f).SetSpeedBased();
        }

        protected Action _OnLookAtEnd;
        public CameraBase WaitLookAtEnd(Action onLookAtEnd)
        {
            this._OnLookAtEnd = onLookAtEnd;
            return this;
        }



        //适配相机Z 位置<<--- 对象得 边缘..
        Vector2 _CrremtLookOffset;
        void _SuitViewFor(Transform where, Bounds bound, float zoom = 0f, float delay = 0)
        {
            if (IsRouting) return;
            StopAllCoroutines();
            StartCoroutine(_ViewSuiter(where, bound, zoom, delay));
        }
        IEnumerator _ViewSuiter(Transform where, Bounds bound, float zoom = 0, float delay = 0)
        {
            yield return new WaitForSeconds(delay);


            //_MainCamer.transform.DOLocalMove( Vector3.zero,0.2f);

            float speed = Config.SuitSpeed;
            if (zoom <= 0) zoom = Config.LookBoundZoom;

            bound.size *= zoom;

            bool isin, _isin_start = MainCamera.ISInView(where, bound);
            Vector3 pos = transform.position;

            bool _suiting = true;
            do
            {
                isin = MainCamera.ISInView(where, bound);

                if (_isin_start != isin)
                {
                    // transform.position = pos;
                    _suiting = false;

                }
                else
                {
                    pos = transform.position;
                    Vector3 dir = MainCamera.transform.forward * (isin ? 1 : -1);


                    if (!_MoveOnDirection(dir, speed * 0.01f))
                    {
                        _suiting = false;
                    }
                    //transform.position += dir * speed * 0.01f;

                    speed *= Config.SuitExponent;

                    yield return 0;
                }


            } while (_suiting);

            if (_CrremtLookOffset.magnitude > 0.03f)
                LookOffset(_CrremtLookOffset);

            yield return 1;
        }
        void _SuitViewFor(Transform where, float zoom, float delay = 0)
        {

            IBoundOwner bound = where.GetComponent<IBoundOwner>();

            if (bound != null)
            {
                _SuitViewFor(where, bound.Bound, zoom, Config.FocusDelay);
            }
        }

        /// <summary>
        /// 使用相机位置+ Bonud 计算合法性
        /// </summary>
        /// <returns></returns>
        bool _IsViewOutBound_Simple()
        {
            if (BoundOwner == null)
                return false;

            Vector3 pos = transform.position;

            if (BoundOwner.transform != null)
                pos = BoundOwner.transform.InverseTransformPoint(pos);
            pos.y = 5;
            //if (!Bound.Bound.Contains(pos))
            //    return true;

            if (BoundOwner.Bound != null)
                return !BoundOwner.Bound.Contains(pos);

            return false;
        }
        /// <summary>
        /// 超出视野的边缘点。w>0有效
        /// </summary>
        /// <returns></returns>
        Vector4 _ViewOutBoundSidePiont_Simple()
        {
            if (BoundOwner != null)
            {
                Vector4 curr = transform.position;
                curr.w = 0;
                if (BoundOwner.transform != null)
                {
                    var locPos = BoundOwner.transform.InverseTransformPoint(curr);
                    locPos.y = 5;
                    if (!BoundOwner.Bound.Contains(locPos))
                    {
                        float adj_x = curr.x;
                        if (locPos.x < BoundOwner.Bound.center.x - BoundOwner.Bound.extents.x)
                        {
                            adj_x += BoundOwner.Bound.center.x - BoundOwner.Bound.extents.x - locPos.x + 0.05f;
                        }
                        else if (locPos.x > BoundOwner.Bound.center.x + BoundOwner.Bound.extents.x)
                        {
                            adj_x -= locPos.x - (BoundOwner.Bound.center.x + BoundOwner.Bound.extents.x) + 0.05f;
                        }

                        float adj_z = curr.z;
                        if (locPos.z < BoundOwner.Bound.center.z - BoundOwner.Bound.extents.z)
                        {
                            adj_z += BoundOwner.Bound.center.z - BoundOwner.Bound.extents.z - locPos.z + 0.05f;
                        }
                        else if (locPos.z > BoundOwner.Bound.center.z + BoundOwner.Bound.extents.z)
                        {
                            adj_z -= locPos.z - (BoundOwner.Bound.center.z + BoundOwner.Bound.extents.z) + 0.05f;
                        }

                        curr.x = adj_x;
                        curr.z = adj_z;
                        curr.w = 1;
                    }
                }
                return curr;
            }
            return Vector4.zero;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="viewport_offset">希望偏移得量,针对屏幕百分比</param>
        public CameraBase LookOffset(Vector2 viewport_offset)
        {
            if (IsRouting) return this;
            _CrremtLookOffset = viewport_offset;

            if (viewport_offset.magnitude <= 0.03f)
            {
                MainCamera.transform.localPosition = Vector3.zero;
                return this;
            }
            //屏幕百分比 对找到 世界坐标.
            float dist = transform.position.y;

            Vector3[] vps = new Vector3[4];

            MainCamera.CalculateFrustumCorners(new Rect() { min = Vector2.zero, max = Vector2.one }, dist, Camera.MonoOrStereoscopicEye.Mono, vps);

            float width = Vector3.Distance(vps[0], vps[3]);
            float height = Vector3.Distance(vps[0], vps[1]);

            var of = new Vector3(width * viewport_offset.x, 0, height * viewport_offset.y);

            Vector3 posz = Vector3.Cross(MainCamera.transform.right, Vector3.up) * of.z;
            Vector3 posx = MainCamera.transform.right * of.x;

            MainCamera.transform.DOKill();
            MainCamera.transform.DOMove(transform.position + posz + posx, 0.3f);

            return this;
        }


        /// <summary>
        /// 获取观测点
        /// </summary>
        /// <param name="target"></param>
        /// <param name="camerahigh"></param>
        /// <returns></returns>
        protected Vector3 _GetLookAtPosition(Vector3 target, float camerahigh = 0f)
        {

            if (Mathf.Approximately(camerahigh, 0f))
            {
                camerahigh = transform.position.y;
            }
            Vector3 dir = -Forward.forward;// -1 * (Camera.main.transform.rotation * Vector3.forward);


            Vector3 p = _Line_PANEL(target, dir, Vector3.up, Vector3.up * camerahigh);

            return p;
        }
    }



}

